﻿using System;
using System.Data;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Web.Mvc;
using System.Web.Routing;
using Microsoft.Practices.Unity;
using WebShop.Contracts;
using WebShop.DAL;
using WebShop.DAL.Interfaces;
using WebShop.DAL.Repositories;
using Webdiyer.WebControls.Mvc;
using WebShop.Infrastructure;
using WebShop.Models;
using WebShop.ViewModels;

namespace WebShop.Controllers
{
    [Authorize]
    [HandleErrors]
    public class ProductsController : Controller
    {
        private const int PAGE_SIZE = 20;
        private const int QUICK_SEARCH_RESULTS = 10;

        [Dependency]
        public IProductRepository Products { get; set; }

        [Dependency]
        public ICategoryRepository Categories { get; set; }

        [Dependency]
        public ISupplierRepository Suppliers { get; set; }

        [Dependency]
        public ProductsCartRepository ProductsCart { get; set; }

        [Dependency]
        public ILogRepository LogRepository { get; set; }
        //
        // GET: /Product/

        [ValidateInput(false)]
        public ActionResult Index(int pageIndex = 1, int categoryID = 0, string q = "")
        {
            PagedList<Product> products = Products.FindList(
                pageIndex,
                PAGE_SIZE,
                p => (p.CategoryID == categoryID || categoryID == 0) && (p.ProductName.Contains(q) || String.IsNullOrEmpty(p.ProductName)),
                p => p.ProductName
            );

            if (!string.IsNullOrEmpty(q))
            {
                ViewBag.q = q;
            }

            if (Request.IsAjaxRequest())
            {
                return PartialView("_ProductList", products);
            }
            return View(products);
        }

        //
        // GET: /Product/Details/5

        public ViewResult Details(int id)
        {
            ProductsCart cart = ProductsCart.LoadCart(HttpContext);
            ProductInCart productInCart = cart.GetProduct(id);

            if (productInCart == null)
            {
                ViewBag.QuantityInCart = 0;
            }
            else
            {
                ViewBag.QuantityInCart = productInCart.Quantity;
            }
            Product product = Products.Get(id);
            return View(product);
        }

        //
        // GET: /Product/Create

        public ActionResult Create()
        {
            ViewBag.CategoryID = new SelectList(Categories.List(), "CategoryID", "CategoryName");
            ViewBag.SupplierID = new SelectList(Suppliers.List(), "SupplierID", "CompanyName");

            return View();
        }

        //
        // POST: /Product/Create

        [HttpPost]
        [ValidateAntiForgeryToken]
        [ValidateInput(false)]
        public ActionResult Create(Product product)
        {
            if (ModelState.IsValid)
            {
                Products.Create(product);
                Products.SaveChanges();
                return Redirect(Url.ProductsList(1, product.CategoryID.GetValueOrDefault()));
            }

            ViewBag.CategoryID = new SelectList(Categories.List(), "CategoryID", "CategoryName", product.CategoryID);
            ViewBag.SupplierID = new SelectList(Suppliers.List(), "SupplierID", "CompanyName", product.SupplierID);

            return View(product);
        }

        //
        // GET: /Product/Edit/5

        public ActionResult Edit(int id)
        {
            Product product = Products.Get(id);
            ViewBag.CategoryID = new SelectList(Categories.List(), "CategoryID", "CategoryName", product.CategoryID);
            ViewBag.SupplierID = new SelectList(Suppliers.List(), "SupplierID", "CompanyName", product.SupplierID);

            return View(product);
        }

        //
        // POST: /Product/Edit/5

        [HttpPost]
        [ValidateAntiForgeryToken]
        [ValidateInput(false)]
        public ActionResult Edit(Product product)
        {
            if (ModelState.IsValid)
            {
                try
                {
                    Products.Edit(product);
                    Products.SaveChanges();
                    return Redirect(Url.ProductsList(1, product.CategoryID.GetValueOrDefault()));
                }
                catch (DbUpdateConcurrencyException)
                {
                    Products.Detach(product);
                    Product databaseProduct = Products.Get(product.ProductID);
                    if (databaseProduct.ProductName != product.ProductName)
                        ModelState.AddModelError("ProductName", "Current value: " + databaseProduct.ProductName);
                    if (databaseProduct.SupplierID != product.SupplierID)
                        ModelState.AddModelError("SupplierID", "Current value: " + databaseProduct.Supplier.CompanyName);
                    if (databaseProduct.CategoryID != product.CategoryID)
                        ModelState.AddModelError("CategoryID", "Current value: " + databaseProduct.Category.CategoryName);
                    if (databaseProduct.QuantityPerUnit != product.QuantityPerUnit)
                        ModelState.AddModelError("QuantityPerUnit", "Current value: " + databaseProduct.QuantityPerUnit);
                    if (databaseProduct.UnitPrice != product.UnitPrice)
                        ModelState.AddModelError("UnitPrice", "Current value: " + databaseProduct.UnitPrice);
                    if (databaseProduct.UnitsInStock != product.UnitsInStock)
                        ModelState.AddModelError("UnitsInStock", "Current value: " + databaseProduct.UnitsInStock);
                    if (databaseProduct.UnitsOnOrder != product.UnitsOnOrder)
                        ModelState.AddModelError("UnitsOnOrder", "Current value: " + databaseProduct.UnitsOnOrder);
                    if (databaseProduct.ReorderLevel != product.ReorderLevel)
                        ModelState.AddModelError("ReorderLevel", "Current value: " + databaseProduct.ReorderLevel);
                    if (databaseProduct.Discontinued != product.Discontinued)
                        ModelState.AddModelError("Discontinued", "Current value: " + databaseProduct.Discontinued);
                    ModelState.AddModelError(string.Empty, "The record you attempted to edit "
                       + "was modified by another user after you got the original value. The "
                       + "edit operation was canceled and the current values in the database "
                       + "have been displayed.");
                }
                catch (DataException)
                {
                    /////Log the error (add a variable name after Exception) 
                    ModelState.AddModelError(string.Empty, "Unable to save changes. Try again, and if the problem persists contact your system administrator.");
                }
            }
            ViewBag.CategoryID = new SelectList(Categories.List(), "CategoryID", "CategoryName", product.CategoryID);
            ViewBag.SupplierID = new SelectList(Suppliers.List(), "SupplierID", "CompanyName", product.SupplierID);

            return View(product);
        }

        //
        // GET: /Product/Delete/5

        public ActionResult Delete(int id, bool? concurrencyError)
        {
            Product product = Products.Get(id);

            if (concurrencyError.GetValueOrDefault())
            {
                ViewBag.ConcurrencyErrorMessage = "The record you attempted to delete "
                    + "was modified by another user after you got the original values. "
                    + "The delete operation was canceled and the current values in the "
                    + "database have been displayed.";
            }

            return View(product);
        }

        //
        // POST: /Product/Delete/5

        [HttpPost, ActionName("Delete")]
        public ActionResult DeleteConfirmed(int id)
        {
            Product product = Products.Get(id);

            if (product == null)
            {
                return Redirect(Url.ProductsList());
            }

            try
            {
                Products.Delete(id);
                Products.SaveChanges();
                return Redirect(Url.ProductsList());
            }
            catch (DbUpdateConcurrencyException)
            {
                return RedirectToAction("Delete", new RouteValueDictionary { { "concurrencyError", true } });
            }
            catch (DbUpdateException ex)
            {
                LogRepository.Add(ex, HttpContext.User.Identity.Name);
                ModelState.AddModelError(string.Empty, "Unable to save changes. Try again, and if the problem persists contact your system administrator.");

                return View(product);
            }
        }

        // auto complete results for spotlight search
        public ActionResult QuickSearch(string term)
        {
            var products = Products.QuickSearch(term, QUICK_SEARCH_RESULTS).Select(p => new { label = p.ProductName, id = p.ProductID, value = p.ProductName });

            return Json(products, JsonRequestBehavior.AllowGet);
        }

        [NoCacheActionFilter]
        [Authorize]
        public PartialViewResult AddToCart(int id, short quantity, string cartAction, Product product)
        {
            ProductsCart cart = ProductsCart.LoadCart(HttpContext);

            switch (cartAction)
            {
                case "Add":
                    cart.AddProduct(new ProductInCart(id, quantity));
                    ProductsCart.SaveCart(HttpContext, cart);
                    LogRepository.Add(String.Format("Add product {0} to cart", id), HttpContext.User.Identity.Name);
                    break;
                case "Remove":
                    cart.RemoveProduct(new ProductInCart(id, quantity));
                    ProductsCart.SaveCart(HttpContext, cart);
                    LogRepository.Add(String.Format("Remove product {0} from cart", id), HttpContext.User.Identity.Name);
                    break;
            }

            ProductInCart p = cart.GetProduct(id);
            ViewBag.QuantityInCart = p == null ? 0 : cart.GetProduct(id).Quantity;

            /* if (!Request.IsAjaxRequest())
             {
                 //return RedirectToAction("LogOn", "AccountController");
                 Response.Redirect("/Products/Details/78");
                 //Server.Transfer("y.ua");
             }*/
            return PartialView("_ProductCart", product);
        }

        [AdminOnly]
        public ActionResult Report(DateTime? StartDate, DateTime? EndDate, int pageIndex = 1)
        {
            if (StartDate == null)
            {
                StartDate = DateTime.Now.AddYears(-20);
            }
            if (EndDate == null)
            {
                EndDate = DateTime.Now;
            }

            PagedList<ProductReport> products = Products.Report(StartDate, EndDate, pageIndex, PAGE_SIZE);

            return View(new ProductsReport(products, StartDate, EndDate));
        }

        protected override void Dispose(bool disposing)
        {
            //_products.Dispose();
            base.Dispose(disposing);
        }
    }
}